package com.my.spring.framework.aop;

import com.my.spring.framework.aop.config.MyAopConfig;
import com.my.spring.framework.aop.support.MyAdvisedSupport;
import com.my.spring.framework.beans.config.MyBeanDefinition;
import com.my.spring.framework.beans.config.MyBeanPostProcessor;
import com.my.spring.framework.context.MyApplicationContext;

import java.util.Properties;

public class MyAutoProxyCreator implements MyBeanPostProcessor {
    private MyApplicationContext applicationContext;

    // spring不是这样的
    public MyAutoProxyCreator(MyApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws Exception {
        return wrapIfNecessary(bean, beanName);
    }
    private Object wrapIfNecessary(Object bean, String beanName) {
        MyAdvisedSupport aopConfig = instantiateAopConfig();
        aopConfig.setTargetClass(bean.getClass());
        aopConfig.setTarget(bean);
        if (aopConfig.pointCutMatch()) {
            bean = createProxy(aopConfig).getProxy();
        }
        return bean;
    }

    private MyAdvisedSupport instantiateAopConfig() {
        Properties appConfig = applicationContext.getConfig();
        MyAopConfig config = new MyAopConfig();
        config.setPointCut(appConfig.getProperty("pointCut"));
        config.setAspectBefore(appConfig.getProperty("aspectBefore"));
        config.setAspectAfter(appConfig.getProperty("aspectAfter"));
        config.setAspectAfterThrow(appConfig.getProperty("aspectAfterThrow"));
        config.setAspectAfterThrowingName(appConfig.getProperty("aspectAfterThrowingName"));
        config.setAspectClass(appConfig.getProperty("aspectClass"));
        return new MyAdvisedSupport(config);
    }

    private MyAopProxy createProxy(MyAdvisedSupport config) {
        Class<?> clazz = config.getTargetClass();
        if (clazz.getInterfaces().length > 0) {
            return new MyJdkDynamicAopProxy(config);
        }
        return new MyCglibAopProxy(config);
    }
}
